"""Cinema 4D host adapter — everything `_core` needs to know about this DCC.

The twin of tools/blender/three_blocks/host.py: same six constants, same four
resolvers, same three bound api calls (docs/plans/three-blocks-cinema4d-addon.md §3).
"""

from __future__ import annotations

import json
import platform
from pathlib import Path

import c4d

from ._core import api

HOST_KEY = "c4d"  # ~/.three-blocks/c4d/{addons,installed.json}
CLIENT_ID = "c4d-addon"  # device-flow client (free-form server-side)
VALIDATE_TOOL = "c4d-hub"  # /api/tools/validate `tool` — telemetry only
CATALOG_PATH = "/api/c4d/catalog"

# The analytics source is assigned by the ROUTE, and `blender-event` hardcodes
# source="blender" while the growthEvent enum has no "c4d" — so posting there
# would mislabel every C4D bake. The generic route accepts tool_job_completed
# from source "tool", which is honest and needs no server change (plan §7).
EVENT_PATH = "/api/analytics/v2/event"
EVENT_SOURCE = "c4d"  # telemetry idempotency namespace


def site_url() -> str:
    """TB_SITE_URL → WorldPluginData override → prod, so a Dock-launched C4D
    pointed at a sandbox hands tools the sandbox token (mirrors Blender prefs)."""
    from . import prefs

    return prefs.effective_site_url()


def host_version() -> str:
    # GetC4DVersion() encodes the marketing version: 2026.3 → 2026300 (and the
    # older R-series → 26300, which reads as "26.3").
    version = c4d.GetC4DVersion()
    return f"{version // 1000}.{(version // 100) % 10}"


def label() -> str:
    return f"Cinema 4D {host_version()}"


def online_allowed() -> bool:
    """Cinema 4D has no `bpy.app.online_access` equivalent — Preferences ▸
    Communication governs only Maxon's own telemetry. Keep the hook uniform."""
    return True


def hub_version() -> str:
    """Our own manifest — C4D has no bl_info/blender_manifest analog."""
    try:
        manifest = json.loads((Path(__file__).with_name("tb_hub.json")).read_text(encoding="utf-8"))
        version = manifest.get("version")
        return str(version) if version else "0.0.0"
    except (OSError, ValueError):
        return "0.0.0"


def validate(site: str, token: str):
    return api.validate(site, token, tool=VALIDATE_TOOL, tool_version=hub_version(), label=label())


def catalog(site: str, token: str | None = None):
    return api.catalog(site, token=token, path=CATALOG_PATH)


def login_flow(site, emit, should_stop=lambda: False, **kwargs):
    return api.login_flow(
        site,
        emit,
        should_stop,
        client_id=CLIENT_ID,
        device_name=platform.node() or "Cinema 4D",
        validate_credential=validate,
        **kwargs,
    )
